package com.gun.management.module.raffle.service.lotterylog;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.gun.management.framework.common.exception.ServiceException;
import com.gun.management.framework.common.pojo.PageResult;
import com.gun.management.framework.mybatis.core.util.MyBatisUtils;
import com.gun.management.module.member.dal.dataobject.point.MemberPointRecordDO;
import com.gun.management.module.member.dal.dataobject.user.MemberUserDO;
import com.gun.management.module.member.dal.mysql.point.MemberPointRecordMapper;
import com.gun.management.module.member.dal.mysql.user.MemberUserMapper;
import com.gun.management.module.member.enums.point.MemberPointBizTypeEnum;
import com.gun.management.module.raffle.controller.app.vo.*;
import com.gun.management.module.raffle.dal.dataobject.lottery.LotteryDO;
import com.gun.management.module.raffle.dal.dataobject.lotterylog.LotteryLogDO;
import com.gun.management.module.raffle.dal.dataobject.lotteryrecord.LotteryRecordDO;
import com.gun.management.module.raffle.dal.dataobject.lotteryrule.LotteryRuleDO;
import com.gun.management.module.raffle.dal.mysql.lottery.LotteryMapper;
import com.gun.management.module.raffle.dal.mysql.lotterylog.LotteryLogMapper;
import com.gun.management.module.raffle.dal.mysql.lotteryrecord.LotteryRecordMapper;
import com.gun.management.module.raffle.dal.mysql.lotteryrule.LotteryRuleMapper;
import com.gun.management.module.raffle.dal.mysql.lotteryruleref.LotteryRuleRefMapper;
import com.gun.management.module.system.api.user.AdminUserApi;
import com.xingyuv.captcha.util.StringUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import static com.gun.management.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;

/**
 * 用户抽奖日志 Service 实现类
 *
 * @author 测试账号
 */
@Service
@Validated
@Slf4j
public class LotteryBizServiceImpl implements LotteryBizService {

    @Resource
    private LotteryLogMapper lotteryLogMapper;

    @Resource
    private LotteryMapper lotteryMapper;

    @Resource
    private LotteryRecordMapper lotteryRecordMapper;

    @Resource
    private LotteryRuleMapper lotteryRuleMapper;

    @Resource
    private LotteryRuleRefMapper lotteryRuleRefMapper;

    @Resource
    private MemberUserMapper memberUserMapper;

    @Resource
    private MemberPointRecordMapper memberPointRecordMapper;

    @Resource
    private AdminUserApi userApi;
/*
    @Resource
    private IManagementSupplyOrderApi tradeOrderApi;*/


    /**
     * 根据类型分别展示刮刮卡，九宫格以及大转盘，并获得待抽奖的奖品列表
     * @param telantId
     * @param reqVO
     * @param userId
     * @return
     */
    @Override
    public AppLotteryRespVO getLotteryPrizeList(Long telantId, AppLotteryCategoryReqVO reqVO,Long userId) {

        AppLotteryRespVO appLotteryRespVO = lotteryMapper.selectAppLotteryRespVO(reqVO.getCategoryId());
        if (appLotteryRespVO == null) throw new ServiceException(501, "不存在此类型的抽奖活动，可能抽奖活动不存在或者活动已失效！");

        MemberUserDO memberUserDo = memberUserMapper.selectOne(MemberUserDO::getId, userId);
        if (memberUserDo == null) {
            throw new ServiceException(421, "会员不存在,抽奖失败!");
        }
        // 开始时间：当天开始
        LocalDateTime startOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);

        // 结束时间：当天结束
        LocalDateTime endOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
        // 根据用户id及活动id查询最新的抽奖日志表
        AppUserLatestLotteryRespVO appUserLatestLotteryRespVO = lotteryRecordMapper.selectLatestLotteryRecord(appLotteryRespVO.getId(), memberUserDo.getId(),startOfDay,endOfDay);
        if (appUserLatestLotteryRespVO == null) { // 查询用户表获取积分
            appUserLatestLotteryRespVO = new AppUserLatestLotteryRespVO();

            LotteryDO lotteryDo = lotteryMapper.selectById(appLotteryRespVO.getId());

            appLotteryRespVO.setLeftTimes(lotteryDo.getTotalTimes()); // 抽奖剩余总次数
            appLotteryRespVO.setDayLeftTimes(lotteryDo.getDayTotalTimes()); // 当天剩余抽奖次数
            appLotteryRespVO.setExpenseScore(lotteryDo.getExpenseScore()); // 抽奖消耗积分
            appLotteryRespVO.setBgPicture(lotteryDo.getBgPicture()); // 抽奖活动背景图

            if (memberUserDo == null) {
                appLotteryRespVO.setLeftScore(0); // 用户当前积分
            } else {
                appLotteryRespVO.setLeftScore(memberUserDo.getPoint()); // 用户当前积分
            }
        } else {
            appLotteryRespVO.setLeftTimes(appUserLatestLotteryRespVO.getLeftTimes()); // 抽奖剩余总次数
            appLotteryRespVO.setDayLeftTimes(appUserLatestLotteryRespVO.getDayLeftTimes()); // 当天剩余抽奖次数
            appLotteryRespVO.setExpenseScore(appUserLatestLotteryRespVO.getExpenseScore()); // 抽奖消耗积分
            appLotteryRespVO.setLeftScore(appUserLatestLotteryRespVO.getLeftScore()); // 用户当前积分
            appLotteryRespVO.setBgPicture(appUserLatestLotteryRespVO.getBgPicture()); // 抽奖活动背景图
        }


        appLotteryRespVO.setPrizeList(lotteryRuleRefMapper.selectAppLotteryPrizeList(appLotteryRespVO.getId()));

        return appLotteryRespVO;
    }




    /**
     * APP获得所有户抽奖日志分页
     *
     * @param pageReqVO 分页查询
     * @return APP获得所有用户抽奖日志分页
     */
    @Override
    public PageResult<AppUserLotteryLogRespVO> getAllUsersLotteryLogPage(Long userId, Long telantId, AppLotteryLogPageReqVO pageReqVO) {
        PageResult<LotteryLogDO> pageList = lotteryLogMapper.selectAllRecordListPage(userId, telantId, pageReqVO);
        List<AppUserLotteryLogRespVO> list = new ArrayList<>();

        for (LotteryLogDO item : pageList.getList()) {
            AppUserLotteryLogRespVO appLotteryLogRespVO = new AppUserLotteryLogRespVO();
            appLotteryLogRespVO.setPrizeName(item.getPrizeName());
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            String formattedLotteryTime = item.getLotteryTime().format(formatter);
            appLotteryLogRespVO.setLotteryTime(formattedLotteryTime);

            list.add(appLotteryLogRespVO);
        }
        ;

        PageResult<AppUserLotteryLogRespVO> appLotteryLogRespVOPageResult = new PageResult<>();
        appLotteryLogRespVOPageResult.setList(list);
        appLotteryLogRespVOPageResult.setTotal(pageList.getTotal());

        return appLotteryLogRespVOPageResult;
    }


    @Override
    public PageResult<AppLotteryLogRespVO> getAppLotteryLogPageList(Long telantId, AppLotteryLogPageReqVO pageReqVO,Long userId) {
        MemberUserDO memberUserDo = memberUserMapper.selectOne(MemberUserDO::getId, userId);
        if (memberUserDo == null) {
            throw new ServiceException(421, "会员不存在,抽奖失败!");
        }
        IPage<AppLotteryLogRespVO> pageResult = lotteryLogMapper.selectAppLotteryLogPageList(MyBatisUtils.buildPage(pageReqVO), pageReqVO.getLotteryId(), null);
        return new PageResult<>(pageResult.getRecords(), pageResult.getTotal());
    }


    @Override
    public PageResult<AppUserLotteryLogRespVO> getAppUserLotteryLogPageList(Long telantId, AppLotteryLogPageReqVO pageReqVO) {
        IPage<AppUserLotteryLogRespVO> pageResult = lotteryLogMapper.selectUserLotteryLogPageList(MyBatisUtils.buildPage(pageReqVO), pageReqVO.getLotteryId(),getLoginUserId());
        return new PageResult<>(pageResult.getRecords(), pageResult.getTotal());
    }

    @Override
    public PageResult<AppYearMonthGroupUserLotteryLogRespVO> getYearMonthGroupLotteryLogList(Long telantId,AppLotteryLogPageReqVO pageReqVO) {
       IPage<AppYearMonthGroupUserLotteryLogRespVO> pageResult = lotteryLogMapper.getYearMonthGroupLotteryLogList(MyBatisUtils.buildPage(pageReqVO), pageReqVO.getLotteryId(),getLoginUserId());
       pageResult.getRecords().stream().forEach(item->{
           item.setList(lotteryLogMapper.selectUserLotteryLogList(pageReqVO.getLotteryId(),getLoginUserId(),item.getGroupName()));
       });

        return new PageResult<>(pageResult.getRecords(), pageResult.getTotal());
    }



    /**
     * APP用户抽奖
     *
     * @param telantId
     * @param reqVO
     * @param userId
     * @return
     */
    @Override
    public AppLotteryPrizeRespVO getPlayResult(Long telantId, AppLotteryReqVO reqVO,Long userId) {
        List<AppLotteryPrizeRespVO> prizes = lotteryRuleMapper.selectAppLotteryPrizeList(reqVO.getLotteryId(), telantId);
        if (prizes != null && prizes.size() == 0) {
            throw new ServiceException(502, "抽奖活动可能已失效！");
        }

        boolean bolRet = getVerifyResult(reqVO.getLotteryId(),userId);

        return getLotteryPrize(reqVO.getLotteryId(),prizes, telantId, userId);
    }


    /**
     * 根据Math.random()产生一个double型的随机数，判断每个奖品出现的概率
     *
     * @param lotteryId
     * @param prizes
     * @param telantId
     * @return
     */
    @Transactional(rollbackFor = {ServiceException.class,RuntimeException.class,Throwable.class,Exception.class})
    public AppLotteryPrizeRespVO getLotteryPrize(Long lotteryId, List<AppLotteryPrizeRespVO> prizes, Long telantId, Long userId) {
        int random = -1;
        MemberUserDO memberUserDo = memberUserMapper.selectOne(MemberUserDO::getId, userId);
        if (memberUserDo == null) {
            throw new ServiceException(421, "会员不存在,抽奖失败!");
        }

        LotteryDO lotteryDO = lotteryMapper.selectById(lotteryId);
        if (lotteryDO == null) {
            throw new ServiceException(422, "抽奖活动不存在,抽奖失败!");
        }
        else {
            if (lotteryDO.getStatus() == 1) {
                throw new ServiceException(422, "抽奖活动已暂停启用,抽奖失败!");
            }
        }

        //计算总权重
        double sumWeight = 0;
        for (AppLotteryPrizeRespVO prizeItem : prizes) {
            sumWeight += prizeItem.getPrizeProbability();
        }

        //产生随机数
        double randomNumber = Math.random();

        //根据随机数在所有奖品分布的区域并确定所抽奖品
        double d1 = 0;
        double d2 = 0;

        for (int i = 0; i < prizes.size(); i++) {
           d2 += Double.parseDouble(String.valueOf(prizes.get(i).getPrizeProbability())) / sumWeight;
            if (i == 0) {
                d1 = 0;
            } else {
                d1 += Double.parseDouble(String.valueOf(prizes.get(i - 1).getPrizeProbability())) / sumWeight;
            }
            if (randomNumber >= d1 && randomNumber <= d2) {
                random = i;

                LotteryRuleDO lotteryRuleDO = lotteryRuleMapper.selectById(prizes.get(random).getPrizeId());
                if (lotteryRuleDO != null && lotteryRuleDO.getPrizeQty() != null ) {

                    if (lotteryRuleDO.getPrizeQty() != -1 && lotteryRuleDO.getPrizeQty() > 0) {
                        prizes.get(random).setPrizeQty(lotteryRuleDO.getPrizeQty()); // 抽奖有效
                    }
                    if (lotteryRuleDO.getPrizeQty() == 0) {
                        prizes.get(random).setPrizeQty(0); // 抽奖无效
                        prizes.get(random).setPrizeProbability(0);  // 将中奖概率降低
                        log.info("*****中奖的是:" + prizes.get(random).getName() + ",当前剩余数量:" + prizes.get(random).getPrizeQty());
                    }
                    if (lotteryRuleDO.getPrizeQty() == -1) {
                        prizes.get(random).setPrizeQty(-1); // 抽奖有效
                    }

                } else {
                        prizes.get(random).setPrizeQty(0);

                }
                if (prizes.get(random).getPrizeQty() ==0) { // 如果奖品数量为0，则概率为0
                     i = 0;
                    random = 0;
                    log.info("****无效中奖的是:" + prizes.get(random).getName() + ",当前剩余数量:" + prizes.get(random).getPrizeQty());
                     continue;
                } else {
                    log.info("****有效中奖的是:" + prizes.get(random).getName() + ",当前剩余数量:" + prizes.get(random).getPrizeQty());
                    break;
                }
            }
        }

        // 1.查询用户当前的积分，如果获取的是奖品为积分，则更新
        if (memberUserDo.getPoint() < prizes.get(random).getExpenseScore()) {
            throw new ServiceException(421, "会员积分不够,抽奖失败!");
        }

        boolean bolFlag = getVerifyResult(prizes.get(random).getLotteryId(), userId);

        // 扣除消耗的积分
        int leftPoint = (memberUserDo.getPoint() - prizes.get(random).getExpenseScore());

        LambdaUpdateWrapper<MemberUserDO> memberUserDOLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        memberUserDOLambdaUpdateWrapper.set(MemberUserDO::getPoint, leftPoint).eq(MemberUserDO::getId, memberUserDo.getId());
        // 更新最新的积分至用户会员积分表
        memberUserMapper.update(null, memberUserDOLambdaUpdateWrapper);

        // 3.添加奖品至raffle_lottery_record（待处理）
        // 此处要判断当天不允许超过次数,另外累计不允许超过允许的总次数,最后消耗积分后,要记录好流水数据
        LambdaQueryWrapper<LotteryRecordDO> lotteryRecordDOLambdaQueryWrapper = Wrappers.lambdaQuery();
        lotteryRecordDOLambdaQueryWrapper.eq(LotteryRecordDO::getUserId, memberUserDo.getId());
        lotteryRecordDOLambdaQueryWrapper.eq(LotteryRecordDO::getLotteryId,lotteryId);
        lotteryRecordDOLambdaQueryWrapper.eq(LotteryRecordDO::getTenantId, telantId);

        // 开始时间：当天开始
        LocalDateTime startOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);

        // 结束时间：当天结束
        LocalDateTime endOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);

        lotteryRecordDOLambdaQueryWrapper.ge(LotteryRecordDO::getLotteryTime, startOfDay);
        lotteryRecordDOLambdaQueryWrapper.le(LotteryRecordDO::getLotteryTime, endOfDay);

        lotteryRecordDOLambdaQueryWrapper.orderByDesc(LotteryRecordDO::getId);
        List<LotteryRecordDO> lotteryRecordList = lotteryRecordMapper.selectList(lotteryRecordDOLambdaQueryWrapper);
        AppUserLotterySummaryRespVO  appUserLotterySummaryRespVO = lotteryRecordMapper.selectUserLotterySummaryRecord(lotteryId,memberUserDo.getId(),startOfDay,endOfDay);


        Integer leftTimes = 0;   // 抽奖剩余次数
        Integer dayLeftTimes = 0;  //  每人每天抽奖剩余次数

        if (appUserLotterySummaryRespVO != null && appUserLotterySummaryRespVO.getUserDayLotteryTimes() >  0 ) {
            LotteryRecordDO lotteryRecordDO = lotteryRecordList.get(0); // 获取最近一条记录

            leftTimes = prizes.get(random).getTotalTimes() -  appUserLotterySummaryRespVO.getUserDayLotteryTimes();
            dayLeftTimes = prizes.get(random).getDayTotalTimes()  -  appUserLotterySummaryRespVO.getUserDayLotteryTimes();
            if (leftTimes <= 0) {
                throw new ServiceException(507, "平台允许每人抽奖剩余次数已为0,不允许抽奖!");
            }
            if (dayLeftTimes <= 0) {
                throw new ServiceException(508, "平台允许每人每天抽奖剩余次数已为0,不允许抽奖!");
            }
            if (lotteryRecordDO.getLeftScore() <= 0) {
                throw new ServiceException(509, "用户剩余积分已为0,不允许抽奖!");
            }
        }

        LotteryRecordDO lotteryRecordDO = new LotteryRecordDO();
        lotteryRecordDO.setLotteryTime(LocalDateTime.now());
        lotteryRecordDO.setUserId(memberUserDo.getId());
        lotteryRecordDO.setTenantId(telantId);
        lotteryRecordDO.setTotalTimes(prizes.get(random).getTotalTimes()); // 每人抽奖总次数
        lotteryRecordDO.setDayTotalTimes(prizes.get(random).getDayTotalTimes());  // 每人每天抽奖次数
        lotteryRecordDO.setExpenseScore(-prizes.get(random).getExpenseScore());  // 本次抽奖消耗积分
        lotteryRecordDO.setLeftScore(leftPoint);  // 剩余积分

        lotteryRecordDO.setLotteryId(prizes.get(random).getLotteryId()); //  本次抽奖ID
        lotteryRecordDO.setRuleId(prizes.get(random).getPrizeId()); // 本次抽到的奖金ID
        if (prizes.get(random).getPrizeCategory() != 20) {
            lotteryRecordDO.setStatus(1); // 抽奖状态更改成已中奖
        }
        else {
            lotteryRecordDO.setStatus(0); // 抽奖状态更改成未中奖
        }
        lotteryRecordDO.setCreateTime(LocalDateTime.now());

        lotteryRecordMapper.insertAndGetId(lotteryRecordDO);

        MemberPointRecordDO memberPointRecordDO1 = new MemberPointRecordDO();
        memberPointRecordDO1.setUserId(memberUserDo.getId());
        if (lotteryDO.getCategoryId() == 1) { // 九宫格
            memberPointRecordDO1.setBizType(MemberPointBizTypeEnum.NINE_SQUARE_GRID.getType()); // 九宫格
            memberPointRecordDO1.setDescription("单次九宫格抽奖消耗" + prizes.get(random).getExpenseScore() + "积分");
        } else if (lotteryDO.getCategoryId() == 2) { // 大转盘
            memberPointRecordDO1.setBizType(MemberPointBizTypeEnum.BIG_WHEEL.getType()); // 大转盘
            memberPointRecordDO1.setDescription("单次大转盘抽奖消耗" + prizes.get(random).getExpenseScore() + "积分");
        } else if (lotteryDO.getCategoryId() == 3) { // 刮刮卡
            memberPointRecordDO1.setBizType(MemberPointBizTypeEnum.SCRATCH_CARD.getType()); // 刮刮卡
            memberPointRecordDO1.setDescription("单次刮刮卡抽奖消耗" + prizes.get(random).getExpenseScore() + "积分");
        }

        memberPointRecordDO1.setBizId(String.valueOf(lotteryRecordDO.getId())); // 此处待确认
        memberPointRecordDO1.setUserId(memberUserDo.getId());
        memberPointRecordDO1.setPoint(-prizes.get(random).getExpenseScore());
        memberPointRecordDO1.setTotalPoint(leftPoint);
        memberPointRecordDO1.setTitle("会员积分");
        memberPointRecordDO1.setDeleted(false);
        memberPointRecordDO1.setCreateTime(LocalDateTime.now());
        memberPointRecordDO1.setCreator(String.valueOf(memberUserDo.getId()));
        memberPointRecordDO1.setUpdateTime(LocalDateTime.now());
        // 单次抽奖消耗积分，添加消耗积分至用户积分记录表
        memberPointRecordMapper.insert(memberPointRecordDO1);

        if (prizes.get(random).getPrizeCategory() != 20) { // 未中奖的记录不加入到中奖记录列表中


            // 4.添加奖品至raffle_lottery_log（待处理）
            LotteryLogDO lotteryLogDO = new LotteryLogDO();
            lotteryLogDO.setExpenseScore(-prizes.get(random).getExpenseScore());
            lotteryLogDO.setStatus(0); // 奖品状态(0:待领取 1：已领取未处理 2:处理成功 3:处理失败)
            lotteryLogDO.setUserId(memberUserDo.getId());
            lotteryLogDO.setTenantId(telantId);
            lotteryLogDO.setRuleId(prizes.get(random).getPrizeId());
            lotteryLogDO.setPrizeName(prizes.get(random).getName());
            lotteryLogDO.setLotteryTime(LocalDateTime.now());
            lotteryLogDO.setLotteryId(prizes.get(random).getLotteryId());
            lotteryLogDO.setTotalTimes(prizes.get(random).getTotalTimes());
            lotteryLogDO.setDayTotalTimes(prizes.get(random).getDayTotalTimes());
            lotteryLogDO.setCreator(String.valueOf(memberUserDo.getId()));
            lotteryLogDO.setCreateTime(LocalDateTime.now());

            lotteryLogMapper.insertAndGetId(lotteryLogDO);

            prizes.get(random).setLotteryLogId(lotteryLogDO.getId()); // 更新中奖记录id


            log.info("getPrizeIndex===>sumWeight:{}--randomNumber:{}--prizes:{}--会员id:{}抽中的奖品是：{}", sumWeight, randomNumber, prizes, memberUserDo.getId(), prizes.get(random).getName());

        }


        // 如果没有中奖,则直接返回
        if (prizes.get(random).getPrizeCategory() == 20) {
            return prizes.get(random);
        } else {
            LambdaUpdateWrapper<LotteryRuleDO> lotteryRuleDOLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            lotteryRuleDOLambdaUpdateWrapper.eq(LotteryRuleDO::getTenantId, telantId);
            lotteryRuleDOLambdaUpdateWrapper.eq(LotteryRuleDO::getId, prizes.get(random).getPrizeId());
            lotteryRuleDOLambdaUpdateWrapper.eq(LotteryRuleDO::getCategoryId, prizes.get(random).getPrizeCategory());
            if (prizes.get(random).getPrizeQty() != -1 && prizes.get(random).getPrizeQty() >= 1) { // 如果是奖品不是无限的，则扣除
                lotteryRuleDOLambdaUpdateWrapper.set(LotteryRuleDO::getPrizeQty, prizes.get(random).getPrizeQty() - 1);
            }

            lotteryRuleDOLambdaUpdateWrapper.set(LotteryRuleDO::getUpdater, memberUserDo.getId());
            lotteryRuleDOLambdaUpdateWrapper.set(LotteryRuleDO::getUpdateTime, LocalDateTime.now());

            lotteryRuleMapper.update(null, lotteryRuleDOLambdaUpdateWrapper);

            log.info("扣减抽奖活动" + prizes.get(random).getLotteryId() + ",奖品id为:" + prizes.get(random).getPrizeId() + "的奖品数量成功");
            return prizes.get(random);
        }

    }

    /**
     * 获取APP用户领奖结果
     * @param reqVO
     * @return
     */
    /**
     * 获取APP用户领奖结果
     *
     * @param telantId
     * @param reqVO
     * @param userId
     * @return
     */
    public AppLotteryRecvPrizeRespVO getRecvPrizeResult(Long telantId, AppLotteryRecvPrizeReqVO reqVO,Long userId) {
        if (reqVO.getLotteryLogId() == null) {
            throw new ServiceException(101, "中奖记录id参数不能为空!");
        }
        MemberUserDO memberUserDo = memberUserMapper.selectOne(MemberUserDO::getId, userId);
        if (memberUserDo == null) {
            throw new ServiceException(421, "会员用户不存在,您无法领取奖品!");
        }


        // 1.填写信息(供应链实物类-0 直充类-3  卡密类-6  积分类-21  优惠券-22  未中奖-20  自营实物类-99)
        LambdaQueryWrapper<LotteryLogDO> lotteryLogDOLambdaQueryWrapper = Wrappers.lambdaQuery();
        lotteryLogDOLambdaQueryWrapper.eq(LotteryLogDO::getId, reqVO.getLotteryLogId()); // 中奖记录ID
        lotteryLogDOLambdaQueryWrapper.eq(LotteryLogDO::getUserId, getLoginUserId()); // 用户ID
        lotteryLogDOLambdaQueryWrapper.eq(LotteryLogDO::getTenantId, telantId);

        LotteryLogDO lotteryLogDO = lotteryLogMapper.selectOne(lotteryLogDOLambdaQueryWrapper);
        if (lotteryLogDO == null) {
            throw new ServiceException(701, "系统未查询到中奖记录,您无法领取奖品!");
        }
        if (lotteryLogDO.getStatus() == 1 || lotteryLogDO.getStatus() == 2 || lotteryLogDO.getStatus() == 3) {
            throw new ServiceException(702, "当前奖品已被领取，请勿重复认领！");
        }

        LotteryRuleDO lotteryRule = lotteryRuleMapper.selectById(lotteryLogDO.getRuleId());

        String strExtJson = null;

        if (lotteryRule.getCategoryId() == 0 || lotteryRule.getCategoryId() == 99) { // 实物类
            if (reqVO.getAppAddressReqVO() == null) {
                throw new ServiceException(603, "请填写收货地址信息");
            }

            if (StringUtils.isBlank(reqVO.getAppAddressReqVO().getStreetCode())) {
                reqVO.getAppAddressReqVO().setStreetCode(reqVO.getAppAddressReqVO().getDistrictCode());
            }

            if (StringUtils.isBlank(reqVO.getAppAddressReqVO().getStreetName())) {
                reqVO.getAppAddressReqVO().setStreetName(reqVO.getAppAddressReqVO().getDistrictName());
            }

            strExtJson = reqVO.getAppAddressReqVO().toString() ;

        }

        if (lotteryRule.getCategoryId() == 3) { // 直充
            if (reqVO.getAppRechargeReqVO() == null) {
                throw new ServiceException(601, "请填写直充账号");
            }

            strExtJson = reqVO.getAppRechargeReqVO().toString();

        }


        // 2.更改状态

        LambdaUpdateWrapper<LotteryLogDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(LotteryLogDO::getId, lotteryLogDO.getId());
        lambdaUpdateWrapper.set(LotteryLogDO::getStatus, 1); // 更改状态（为已领取状态)
        lambdaUpdateWrapper.set(LotteryLogDO::getExtJson, strExtJson);

        lambdaUpdateWrapper.set(LotteryLogDO::getUpdater, String.valueOf(memberUserDo.getId()));
        lambdaUpdateWrapper.set(LotteryLogDO::getUpdateTime, LocalDateTime.now());
        lotteryLogMapper.update(null, lambdaUpdateWrapper);

        AppLotteryRecvPrizeRespVO appLotteryRecvPrizeRespVO = new AppLotteryRecvPrizeRespVO();

//        ReqApplyTradeOrderVO reqApplyTradeOrderVO = new ReqApplyTradeOrderVO();

        LotteryGoodsRespVO lotteryGoodsRespVO = lotteryRuleMapper.selectLotteryGoodsRespVO(lotteryLogDO.getRuleId());
        if (lotteryGoodsRespVO == null) throw new ServiceException(821, "根据奖品编号未查询到奖品信息，可能是奖品已无库存！");
//        reqApplyTradeOrderVO.setProductId(lotteryGoodsRespVO.getProductId());
//        reqApplyTradeOrderVO.setProductSkuId(lotteryGoodsRespVO.getSkuId());
//        reqApplyTradeOrderVO.setApplyCount(1); // 申请下单数量
//        reqApplyTradeOrderVO.setUserId(memberUserDo.getId()); // 用户id
//        reqApplyTradeOrderVO.setIsVirtual(Integer.parseInt(String.valueOf(lotteryRule.getCategoryId()))); // 奖品类型
//        reqApplyTradeOrderVO.setExtentData(strExtJson); // 扩展信息

        appLotteryRecvPrizeRespVO.setCode("0000");
        appLotteryRecvPrizeRespVO.setMsg("用户领奖成功");
        // 异步执行完成后的操作
        CompletableFuture.supplyAsync(() -> {
//            CommonResult<String> result = tradeOrderApi.applyOrderByProduct(reqApplyTradeOrderVO);
//            log.info("异步执行结果获取订单编号orderNo: " + result.getData());

            LambdaUpdateWrapper<LotteryLogDO> lotteryLogDOLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            lotteryLogDOLambdaUpdateWrapper.eq(LotteryLogDO::getId, lotteryLogDO.getId());
//            lotteryLogDOLambdaUpdateWrapper.set(LotteryLogDO::getOrderNo, result.getData()); // 更改状态（为已领取状态)

            lotteryLogDOLambdaUpdateWrapper.set(LotteryLogDO::getUpdater, String.valueOf(memberUserDo.getId()));
            lotteryLogDOLambdaUpdateWrapper.set(LotteryLogDO::getUpdateTime, LocalDateTime.now());
            lotteryLogDOLambdaUpdateWrapper.set(LotteryLogDO::getStatus, 2); // // 更改状态为处理成功

            lotteryLogMapper.update(null, lotteryLogDOLambdaUpdateWrapper);

//            log.info("异步更新订单编号orderNo: " + result.getData() + "至中奖记录表成功");

            appLotteryRecvPrizeRespVO.setCode("0000");
            appLotteryRecvPrizeRespVO.setMsg("用户领奖成功");

            return appLotteryRecvPrizeRespVO;

        }).exceptionally(ex -> {
            LambdaUpdateWrapper<LotteryLogDO> lotteryLogDOLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            lotteryLogDOLambdaUpdateWrapper.eq(LotteryLogDO::getId, lotteryLogDO.getId());
            lotteryLogDOLambdaUpdateWrapper.set(LotteryLogDO::getStatus, 3); // // 更改状态为处理失败

            lotteryLogDOLambdaUpdateWrapper.set(LotteryLogDO::getUpdater, String.valueOf(memberUserDo.getId()));
            lotteryLogDOLambdaUpdateWrapper.set(LotteryLogDO::getUpdateTime, LocalDateTime.now());
            lotteryLogMapper.update(null, lotteryLogDOLambdaUpdateWrapper);
            log.error("异步获取订单编号异常，更改中奖状态为处理失败");

            appLotteryRecvPrizeRespVO.setCode("1027");
            appLotteryRecvPrizeRespVO.setMsg("用户领奖失败");

            return appLotteryRecvPrizeRespVO;

        });

        // 3.返回结果
        return appLotteryRecvPrizeRespVO;
    }


    /**
     * 抽奖校验
     *
     * @param lotteryId
     * @param userId
     * @return
     */
    public Boolean getVerifyResult(Long lotteryId, Long userId) {
        LotteryDO lotteryDO = lotteryMapper.selectById(lotteryId);
        if (lotteryDO == null) throw new ServiceException(501, "不存在此抽奖活动，无法进行抽奖!");
        if (lotteryDO.getStatus() != 0) {
            throw new ServiceException(502, "抽奖活动" + lotteryDO.getName() + "已禁用，无法进行抽奖!");
        }

        MemberUserDO memberUserDo = memberUserMapper.selectOne( MemberUserDO::getId, userId);
        if (memberUserDo == null) {
            throw new ServiceException(421, "会员不存在，无法进行抽奖!");
        }
        if (memberUserDo.getStatus() != 0) {
            throw new ServiceException(421, "会员" + memberUserDo.getNickname() + "已禁用，无法进行抽奖!!");
        }

        if (memberUserDo.getPoint() <= 0) {
            throw new ServiceException(525, "积分不足");
        }

        // 开始时间：当天开始
        LocalDateTime startOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);

        // 结束时间：当天结束
        LocalDateTime endOfDay = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);

        // 抽奖活动表
        AppUserLatestLotteryRespVO appUserLatestLotteryRespVO = lotteryRecordMapper.selectLatestLotteryRecord(lotteryId, memberUserDo.getId(),startOfDay,endOfDay);
        if (appUserLatestLotteryRespVO != null) {

            if (appUserLatestLotteryRespVO.getLeftScore() <= 0) {
                throw new ServiceException(525, "积分不足");
            }
            if (appUserLatestLotteryRespVO.getLeftTimes() <= 0) {
                throw new ServiceException(526, "当前抽奖活动剩余总次数为0");
            }
            if (appUserLatestLotteryRespVO.getDayLeftTimes() <= 0) {
                throw new ServiceException(527, "当天剩余抽奖次数为0");
            }

        } else {
            if (lotteryDO.getTotalTimes() <= 0) {
                throw new ServiceException(526, "当前抽奖活动剩余总次数为0");
            }

            if (lotteryDO.getDayTotalTimes() <= 0) {
                throw new ServiceException(527, "当天剩余抽奖次数为0");
            }
        }
        return true;
    }

}
